package com.jiufengxinxi.ts.common.utils;

import org.apache.commons.io.FilenameUtils;
import sun.font.FontDesignMetrics;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class ImageUtil {

    /**
     * 把一张BufferedImage图片转化为打印机可以打印的bit
     * @param bit
     * @return
     */
    public static byte[] pic2PxPoint(BufferedImage bit){
        long start = System.currentTimeMillis();
        //byte[] data = new byte[bit.getWidth()*bit.getHeight()];
        byte dataVec[] = new byte[bit.getWidth()*bit.getHeight()/8];
        int k=0;

        int width = bit.getWidth()/8*8;

        StringBuffer dt = new StringBuffer();
        for (int h=0;h<bit.getHeight();h++){
            for (int w=0;w<width;w++){
                dt.append(px2Byte(w,h,bit));
                if(dt.length()==8){
                    dataVec[k++]= (byte) HexUtil.binaryToDecimal(dt.toString());
                    dt.delete(0,dt.length());
                }
            }
        }

        long end = System.currentTimeMillis();

        System.out.println("excute"+(end-start));
        return dataVec;
    }


    /**
     * 图片二值化，黑色是1，白色是0
     * @param x  横坐标
     * @param y	 纵坐标
     * @param ori 位图
     * @return
     */
    public static byte px2Byte(int x, int y, BufferedImage ori) {
//		double[][][] rgbImage = new double[ori.getWidth()][ori.getHeight()][3];
        byte b;
//		int pixel = ori.getRGB(x, y);
        //图片像素点为一个矩阵，需用2个for循环操作像素
        Object data = null;
        try {
            data=ori.getRaster().getDataElements(x, y, null);//获取像素点
        } catch (Exception e) {
            b = 0;
            return b;
        }
        //ColorModel是一个用来将图片某点的rgb值分别取出的类，包括取出alpha值
//        int pixel = ori.getRGB(x, y);
//        int red = (pixel & 0x00ff0000) >> 16; // 取高两位
//        int green = (pixel & 0x0000ff00) >> 8; // 取中两位
//        int blue = pixel & 0x000000ff; // 取低两位
//        int gray = RGB2Gray(red, green, blue);



        int red = ori.getColorModel().getRed(data);
        int green =ori.getColorModel().getGreen(data);
        int blue =  ori.getColorModel().getBlue(data);
        int gray = RGB2Gray(red, green, blue);
//		System.out.println(gray);
        if ( gray < 127 ){
            b = 1;
        } else {
            b = 0;
        }
        return b;
    }

    /**
     * 图片灰度的转化
     * @param r
     * @param g
     * @param b
     * @return
     */
    public static int RGB2Gray(int r, int g, int b){
        int gray = (int) (0.29900 * r + 0.58700 * g + 0.11400 * b);  //灰度转化公式
        return  gray;
    }


    /**
     * @Description: 根据图片地址转换为base64编码字符串
     * @Author:
     * @CreateTime:
     * @return
     */
    public static String getImageStr(String imgFile) {
        InputStream inputStream = null;
        byte[] data = null;
        try {
            inputStream = new FileInputStream(imgFile);
            data = new byte[inputStream.available()];
            inputStream.read(data);
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 加密
        java.util.Base64.Encoder encoder = java.util.Base64.getEncoder();
        return encoder.encodeToString(data);
    }


    /**
     * @Description: 将base64编码字符串转换为图片
     * @Author:
     * @CreateTime:
     * @param imgStr base64编码字符串
     * @param path 图片路径-具体到文件
     * @return
     */
    public static boolean generateImage(String imgStr, String path) {
        if (imgStr == null)
            return false;
        // 解密
        try {
            java.util.Base64.Decoder decoder = java.util.Base64.getDecoder();
            byte[] b = decoder.decode(imgStr);
            // 处理数据
            for (int i = 0; i < b.length; ++i) {
                if (b[i] < 0) {
                    b[i] += 256;
                }
            }
            OutputStream out = new FileOutputStream(path);
            out.write(b);
            out.flush();
            out.close();
            return true;
        } catch (IOException e) {
            return false;
        }
    }

    //每行文本与前段的间隙。
    static final String segment = "  ";

    /**
     * 将Image 图片 转换为 BufferedImage
     * @param image
     * @return
     */
    public static BufferedImage toBufferedImage(Image image) {
        if (image instanceof BufferedImage) {
            return (BufferedImage)image;
        }

        // This code ensures that all the pixels in the image are loaded
        image = new ImageIcon(image).getImage();

        // Determine if the image has transparent pixels; for this method's
        // implementation, see e661 Determining If an Image Has Transparent Pixels
        //boolean hasAlpha = hasAlpha(image);

        // Create a buffered image with a format that's compatible with the screen
        BufferedImage bimage = null;
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        try {
            // Determine the type of transparency of the new buffered image
            int transparency = Transparency.OPAQUE;
	       /* if (hasAlpha) {
	         transparency = Transparency.BITMASK;
	         }*/

            // Create the buffered image
            GraphicsDevice gs = ge.getDefaultScreenDevice();
            GraphicsConfiguration gc = gs.getDefaultConfiguration();
            bimage = gc.createCompatibleImage(
                    image.getWidth(null), image.getHeight(null), transparency);
        } catch (HeadlessException e) {
            // The system does not have a screen
        }

        if (bimage == null) {
            // Create a buffered image using the default color model
            int type = BufferedImage.TYPE_INT_RGB;
            //int type = BufferedImage.TYPE_3BYTE_BGR;//by wang
	        /*if (hasAlpha) {
	         type = BufferedImage.TYPE_INT_ARGB;
	         }*/
            bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), type);
        }

        // Copy image to buffered image
        Graphics g = bimage.createGraphics();

        // Paint the image onto the buffered image
        g.drawImage(image, 0, 0, null);
        g.dispose();

        return bimage;
    }

    public static int getFontPixel(String context,Font font){
        FontMetrics fm = FontDesignMetrics.getMetrics(new Font(font.getName(), Font.PLAIN,font.getSize()));
        return fm.stringWidth(context);
    }

    /**
     * 将文字转换成图片
     * @param str  打印文本
     * @param font  打印字体 如果为NULL  打印默认字体
     * @param outFile 图片输出路径，不需要输出给NULL
     * @param width 图片宽度
     * @param height 图片高度
     * @param qrcodeUrl 二维码URL，不需要NULL
     * @return
     * @throws Exception
     */
    public static BufferedImage createImage(String[] str, Font font, File outFile,
                                            Integer width, Integer height, String qrcodeUrl) throws Exception {
        // 创建图片
        BufferedImage image = new BufferedImage(width, height,
                BufferedImage.TYPE_INT_BGR);
        Graphics g = image.getGraphics();
        g.setClip(0, 0, width, height);
        g.setColor(Color.white);
        g.fillRect(0, 0, width, height);// 先用黑色填充整张图片,也就是背景
        g.setColor(Color.black);// 在换成黑色
        g.setFont(font);// 设置画笔字体
        /** 用于获得垂直居中y */
//        Rectangle clip = g.getClipBounds();
//        FontMetrics fm = g.getFontMetrics(font);
//        int ascent = fm.getAscent();
//        int descent = fm.getDescent();

        int y = 30;

//        int y = (clip.height - (ascent + descent)) / 2 + ascent;


        for (String txt :str) {
            txt  = segment+txt;
            if(font ==null)font = new Font("微软雅黑", Font.PLAIN, 33);
            int fontPixel =  getFontPixel(txt, font);
//            System.out.println(fontPixel);
            boolean overtop =false;
            if(fontPixel > width){
                System.out.println(txt + "超出宽度限制。 ");
                overtop = true;
            }
            List<String> printList = new ArrayList<>();
            if(overtop == true){
                int index = 8;
//              width -=50;
                while (true){

                    String printx = txt.substring(txt.length()-index, txt.length()) ;
                    txt = txt.substring(0, txt.length() - index);
                    index += 1;
                    if(getFontPixel(txt,font) > width){
                        txt += printx;
                        continue;
                    }else{
                        printList.add(txt +"   ");
                        if((getFontPixel(printx,font) > width)){
                            txt = printx;
                            continue;
                        }else {
                            printList.add(segment+printx);
                            break;
                        }
                    }
                }
            }
            if(printList.size() !=0){

                for (String s : printList){
                    for (int i = 0; i < 6; i++) {// 256 340 0 680
                        g.drawString(s, i * 680, y);// 画出字符串QRCodeUtil
                    }
                    y += 42;
                }
                continue;
            }

            for (int i = 0; i < 6; i++) {// 256 340 0 680
                g.drawString(txt, i * 680, y);// 画出字符串
            }
            y += 41;
        }
        //画二维码
        if(!qrcodeUrl.equals("")){
            BufferedImage qrcode =  QRCodeUtil.encode(qrcodeUrl,"","",false);
            g.drawImage(qrcode,356,0,qrcode.getWidth(),qrcode.getHeight(),null);
        }
        g.dispose();
        if(outFile !=null){
            ImageIO.write(image, "png", outFile);// 输出png图片
        }
        return image;
    }


    /**
     * 改变图片的尺寸
     *
     * @param newWidth, newHeight, path
     * @return boolean
     */
    public static boolean changeSize(int newWidth, int newHeight, String path) {
        BufferedInputStream in = null;
        try {
            in = new BufferedInputStream(new FileInputStream(path));

            //字节流转图片对象
            Image bi = ImageIO.read(in);
            //构建图片流
            BufferedImage tag = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);
            //绘制改变尺寸后的图
            tag.getGraphics().drawImage(bi, 0, 0, newWidth, newHeight, null);
            //输出流
            BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(path));
            //JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
            //encoder.encode(tag);
            ImageIO.write(tag, FilenameUtils.getExtension(path).toUpperCase(), out);
            in.close();
            out.close();
            return true;
        } catch (IOException e) {
            return false;
        }
    }

    /*
     * 图片缩放,w，h为缩放的目标宽度和高度
     * src为源文件目录，dest为缩放后保存目录
     */
    public static void zoomImage(String src,String dest,int w,int h) throws Exception {

        double wr=0,hr=0;
        File srcFile = new File(src);
        File destFile = new File(dest);

        BufferedImage bufImg = ImageIO.read(srcFile); //读取图片
        Image Itemp = bufImg.getScaledInstance(w, h, bufImg.SCALE_SMOOTH);//设置缩放目标图片模板

        wr=w*1.0/bufImg.getWidth();     //获取缩放比例
        hr=h*1.0 / bufImg.getHeight();

        AffineTransformOp ato = new AffineTransformOp(AffineTransform.getScaleInstance(wr, hr), null);
        Itemp = ato.filter(bufImg, null);
        try {
            ImageIO.write((BufferedImage) Itemp,FilenameUtils.getExtension(dest).toUpperCase(), destFile); //写入缩减后的图片
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    /*
     * 图片按比率缩放
     * size为文件大小
     */
    public static void zoomImage(String src,String dest,Integer size) throws Exception {
        File srcFile = new File(src);
        File destFile = new File(dest);

        long fileSize = srcFile.length();
        if(fileSize < size * 1024)   //文件大于size k时，才进行缩放,注意：size以K为单位
            return;

        Double rate = (size * 1024 * 0.5) / fileSize; // 获取长宽缩放比例

        BufferedImage bufImg = ImageIO.read(srcFile);
        Image Itemp = bufImg.getScaledInstance(bufImg.getWidth(), bufImg.getHeight(), bufImg.SCALE_SMOOTH);

        AffineTransformOp ato = new AffineTransformOp(AffineTransform.getScaleInstance(rate, rate), null);
        Itemp = ato.filter(bufImg, null);
        try {
            ImageIO.write((BufferedImage) Itemp,FilenameUtils.getExtension(dest).toUpperCase(), destFile);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public static boolean getSubimageByRate(String src,String dest,float leftRate,float rightRate,float topRate, float bottomRate){
        try {
            BufferedImage bufImage = ImageIO.read(new File(src));
            int width = bufImage.getWidth();
            int height = bufImage.getHeight();
            int x = (int)(width * leftRate /100);
            int y = (int)(height * topRate /100);
            int w = (int)(width * rightRate /100 - x);
            int h = (int)(height * bottomRate /100 -y);
            bufImage = bufImage.getSubimage(x,y,w,h);
            ImageIO.write(bufImage,FilenameUtils.getExtension(dest).toUpperCase(), new File(dest));
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }


    public static void main(String[] args) throws Exception {
        getSubimageByRate("/Users/heshuangfeng/Pictures/扫描.jpeg","/Users/heshuangfeng/Pictures/扫描.jpeg",10,80,10,
                70);
    }

}
